home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************\
- * BOUNCE.C - An example Desktop Screen Saver extension by John Ridges
- * Converted to a 32-Bit Screen Blanker module by Peter Wansch
- \***************************************************************************/
-
- #define MAXBITMAPS 25 /* How many happy faces can be on the screen */
-
- #define INCL_DOSMEMMGR
- #define INCL_DOSPROCESS
- #define INCL_GPIBITMAPS
- #define INCL_WINBUTTONS
- #define INCL_WINDIALOGS
- #define INCL_WINENTRYFIELDS
- #define INCL_WININPUT
- #define INCL_WINMESSAGEMGR
- #define INCL_WINTIMER
- #define INCL_WINWINDOWMGR
- #define INCL_WINSHELLDATA
-
- #include <os2.h>
- #include <stdlib.h> /* Needed because SRAND and RAND are called */
-
- typedef struct {
- HAB habBlanker;
- HWND hwndScreen;
- RECTL rclScreen;
- BOOL fClose;
- HMODULE hmodBlanker;
- } BLANKERBLOCK;
-
- typedef BLANKERBLOCK *PBLANKERBLOCK;
-
- PCHAR pchStatus(PBLANKERBLOCK, PBOOL);
- MRESULT EXPENTRY dpBlanker(HWND, ULONG, MPARAM, MPARAM);
- VOID vdBlankerThread(VOID);
-
- static PBLANKERBLOCK pBlankerBlock;
-
- /*
- This is the record that describes the position and velocity of
- a happy face
- */
-
- typedef struct {
- FIXED xvelocity,yvelocity;
- FIXED xposition,yposition;
- } BITMAPREC;
-
- /*
- This is the record that contains the options of the screen saver.
- These options are kept in the OS2.INI profile file.
- */
-
- typedef struct {
- BOOL enabled; /* The screen saver enabled status */
- int numbitmaps; /* The number of happy faces on the screen */
- } PROFILEREC;
-
- static char name[] = "Bounce"; /* The name of this screen saver */
- static BOOL gotprofile = FALSE; /* Indicates that we've read the profile */
- static PROFILEREC profile = {TRUE, 4}; /* Default values */
-
- PCHAR pchStatus(PBLANKERBLOCK initptr, PBOOL enabledptr)
- {
- ULONG i;
-
- /* Save the SAVERBLOCK address locally */
- pBlankerBlock = initptr;
-
- /* Read the profile (but only once!) */
- if (!gotprofile) {
- i = sizeof(PROFILEREC);
- PrfQueryProfileData(HINI_PROFILE,"Blanker",name,&profile,&i);
- gotprofile = TRUE;
- }
- /* Return the enabled status */
- *enabledptr = profile.enabled;
-
- /* Return the screen saver name */
- return name;
- }
-
- MRESULT EXPENTRY dpBlanker(HWND hwnd, ULONG message, MPARAM mp1, MPARAM mp2)
- {
- SHORT i;
-
- switch(message) {
- case WM_INITDLG:
- /* Check the enabled button if enabled */
- if (profile.enabled)
- WinSendDlgItemMsg(hwnd,3,BM_SETCHECK,MPFROMSHORT(1),0);
-
- /* Set the Quantity field */
- WinSetDlgItemShort(hwnd,4,profile.numbitmaps,TRUE);
-
- /* Bring up the dialog */
- WinShowWindow(hwnd,TRUE);
- return FALSE;
-
- case WM_COMMAND:
- /* If OK is pushed */
- if (SHORT1FROMMP(mp1) == 1) {
- /* Get the value of the Quantity field */
- WinQueryDlgItemShort(hwnd,4,&i,TRUE);
-
- /* Check to see if the Quantity is in bounds */
- if (i < 1 || i > MAXBITMAPS) {
- /* Bring up an error message box */
- WinMessageBox(HWND_DESKTOP,hwnd,"The number of happy faces must "
- "be between 1 and 25",NULL,0,MB_OK|MB_ICONHAND);
-
- /* Hilight the Quantity field */
- WinSendDlgItemMsg(hwnd,4,EM_SETSEL,MPFROM2SHORT(0,
- WinQueryDlgItemTextLength(hwnd,4)),0);
-
- /* Give the Quantity field the focus */
- WinSetFocus(HWND_DESKTOP,WinWindowFromID(hwnd,4));
-
- /* Don't exit the dialog */
- return FALSE;
- }
- /* Save the number of happy faces */
- profile.numbitmaps = i;
-
- /* Get the enabled status */
- profile.enabled =
- SHORT1FROMMR(WinSendDlgItemMsg(hwnd,3,BM_QUERYCHECK,0,0));
-
- /* Write the profile data */
- PrfWriteProfileData(HINI_PROFILE,"Blanker",name,&profile,
- sizeof(PROFILEREC));
- }
- }
- return WinDefDlgProc(hwnd,message,mp1,mp2);
- }
-
- VOID vdBlankerThread(VOID)
- {
- HAB hab;
- HPS hps;
- int i;
- FIXED tempx,tempy;
- ULONG sqrt;
- POINTL aptl[4];
- BITMAPREC *bitmaps;
- HBITMAP hbmp;
-
- /* Get an HAB for this thread (since we make PM calls) */
- hab = WinInitialize(0);
-
- /* Get an HPS of the screen */
- hps = WinGetPS(pBlankerBlock->hwndScreen);
-
- /* Paint the screen black */
- WinFillRect(hps,&pBlankerBlock->rclScreen,CLR_BLACK);
-
- /* Get memory for the array of BITMAPRECs */
- bitmaps = NULL;
- DosAllocMem((PPVOID)&bitmaps, sizeof(BITMAPREC)*profile.numbitmaps, PAG_READ | PAG_WRITE | PAG_COMMIT);
-
- /* Flag all the happy faces as 'position unknown' */
- for (i = 0; i < profile.numbitmaps; i++)
- bitmaps[i].xposition = -1L;
-
- /* Get the handle to the happy face and its dimensions */
- hbmp = GpiLoadBitmap(hps,pBlankerBlock->hmodBlanker,1,0L,0L);
- aptl[2].x = aptl[2].y = 0;
- aptl[3].x = aptl[3].y = 34;
-
- /* Randomize RAND using the time */
- srand((unsigned int)WinGetCurrentTime(hab));
-
- /* Loop until Screen Blanker tells us to stop */
- while (!pBlankerBlock->fClose)
-
- /* Process for each happy face */
- for (i = 0; i < profile.numbitmaps; i++) {
-
- /* If the happy face's position is unknown, initialize it */
- if (bitmaps[i].xposition < 0) {
-
- /* Pick a random x velocity between -1 and 1 (fixed) */
- tempx = (long)rand()<<1;
- bitmaps[i].xvelocity = rand()&1 ? tempx : -tempx;
-
- /*
- Make the total velocity 1 by computing:
- yvelocity = sqrt(1 - xvelocity * xvelocity)
- */
- tempy = MAKEFIXED(0,65535)-((ULONG)tempx*(ULONG)tempx>>16);
-
- /* Cheesy sqrt routine to avoid linking in floating point */
- sqrt = 0;
- tempx = 1L<<15;
- do {
- sqrt ^= tempx;
- if (sqrt*sqrt>>16 > (ULONG)tempy) sqrt ^= tempx;
- tempx >>= 1;
- } while (tempx);
-
- /* Randomly set y velocity sign */
- bitmaps[i].yvelocity = rand()&1 ? sqrt : -sqrt;
-
- /* Randomly choose the x and y position of the happy face */
- tempx = MAKEFIXED(pBlankerBlock->rclScreen.xLeft,0)+(rand()*
- (pBlankerBlock->rclScreen.xRight-pBlankerBlock->rclScreen.xLeft-32)<<1);
- tempy = MAKEFIXED(pBlankerBlock->rclScreen.yBottom,0)+(rand()*
- (pBlankerBlock->rclScreen.yTop-pBlankerBlock->rclScreen.yBottom-32)<<1);
- }
- else {
- /* Find the new position of the happy face */
- tempx = bitmaps[i].xposition+bitmaps[i].xvelocity;
- tempy = bitmaps[i].yposition+bitmaps[i].yvelocity;
-
- /* See if the happy face has hit an edge of the screen */
- if (FIXEDINT(tempx) < (int)pBlankerBlock->rclScreen.xLeft) {
-
- /* Bounced off the left edge */
- tempx = (pBlankerBlock->rclScreen.xLeft<<17)-tempx;
- bitmaps[i].xvelocity = -bitmaps[i].xvelocity;
- }
- else if (FIXEDINT(tempx) >= (int)pBlankerBlock->rclScreen.xRight-32) {
-
- /* Bounced off the right edge */
- tempx = (pBlankerBlock->rclScreen.xRight-32<<17)-tempx;
- bitmaps[i].xvelocity = -bitmaps[i].xvelocity;
- }
- if (FIXEDINT(tempy) < (int)pBlankerBlock->rclScreen.yBottom) {
-
- /* Bounced off the bottom edge */
- tempy = (pBlankerBlock->rclScreen.yBottom<<17)-tempy;
- bitmaps[i].yvelocity = -bitmaps[i].yvelocity;
- }
- else if (FIXEDINT(tempy) >= (int)pBlankerBlock->rclScreen.yTop-32) {
-
- /* Bounced off the top edge */
- tempy = (pBlankerBlock->rclScreen.yTop-32<<17)-tempy;
- bitmaps[i].yvelocity = -bitmaps[i].yvelocity;
- }
- }
- /* Draw the happy face in the new position */
- aptl[0].x = FIXEDINT(tempx)-1;
- aptl[0].y = FIXEDINT(tempy)-1;
- aptl[1].x = FIXEDINT(tempx)+32;
- aptl[1].y = FIXEDINT(tempy)+32;
- GpiWCBitBlt(hps,hbmp,4L,aptl,ROP_SRCCOPY,BBO_IGNORE);
-
- /* Save the position of the happy face */
- bitmaps[i].xposition = tempx;
- bitmaps[i].yposition = tempy;
- }
- /* Release the happy face bitmap */
- GpiDeleteBitmap(hbmp);
-
- /* Release the memory for the array of BITMAPRECs */
- DosFreeMem(bitmaps);
-
- /* Release the HPS of the screen */
- WinReleasePS(hps);
-
- /* Get rid of the HAB */
- WinTerminate(hab);
-
- /* Make sure the stack doesn't vanish before we're completely gone */
- DosEnterCritSec();
-
- /* Tell Screen Blanker that we're gone */
-
- pBlankerBlock->fClose = FALSE;
- }